home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / adg_4_6.zip / SCRNBLNK.C < prev    next >
C/C++ Source or Header  |  1991-02-21  |  13KB  |  404 lines

  1. /****************************************************************************
  2. Module name: ScrnBlnk.C
  3. Programmer : Jeffrey M. Richter.
  4. *****************************************************************************/
  5.  
  6. #include "..\nowindws.h"
  7. #undef NOCOLOR
  8. #undef NOCTLMGR
  9. #undef NOGDI
  10. #undef NOHELP
  11. #undef NOKERNEL
  12. #undef NOLSTRING
  13. #undef NOMB
  14. #undef NOMENUS
  15. #undef NOMINMAX
  16. #undef NOMSG
  17. #undef NORASTEROPS
  18. #undef NOSHOWWINDOW
  19. #undef NOSYSMETRICS
  20. #undef NOUSER
  21. #undef NOWH
  22. #undef NOWINOFFSETS
  23. #undef NOWINMESSAGES
  24. #undef NOWINSTYLES
  25. #include <windows.h>
  26. #include <stdlib.h>
  27. #include <math.h>
  28.  
  29. #include "dialog.h"
  30. #include "SB-DLL.h"
  31.  
  32. char _szAppName[] = "ScrnBlnk";
  33. char _szBlnkClass[] = "ScrnBlnkPopup";
  34.  
  35. HANDLE _hInstance = NULL;  // Our instance handle
  36.  
  37. #define IDM_PREFERENCES    (0x0110)   // Must be < 0xF000
  38. #define IDM_ABOUT          (0x0120)   // Must be < 0xF000
  39.  
  40. static WORD _wMinutes = 5;    // Default to 5 minute idle time.
  41. static HWND _hWnd, _hWndBlnk;
  42.  
  43. BOOL NEAR PASCAL RegisterWndClasses (HANDLE hInstance);
  44. LONG FAR PASCAL AppWndProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
  45. LONG FAR PASCAL BlnkWndProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
  46. DWORD FAR PASCAL JrnlRcrdHookFunc (int nCode, WORD wParam, LPEVENTMSGMSG lpEventMsg);
  47. BOOL FAR PASCAL PrefProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam);
  48. BOOL FAR PASCAL AboutProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam);
  49.  
  50. // ***************************************************************************
  51. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) {
  52.    MSG msg;
  53.  
  54.    _hInstance = hInstance;
  55.  
  56.    if (hPrevInstance != NULL) return(0);
  57.  
  58.    if (!RegisterWndClasses(hInstance)) return(0);
  59.  
  60.    // Create application's main window.  Show only as iconic (WS_MINIMIZE).
  61.    _hWnd = CreateWindow(_szAppName, _szAppName,
  62.       WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE, 
  63.       0, 0, 0, 0, NULL, NULL, hInstance, 0);
  64.  
  65.    if (_hWnd == NULL) return(0);
  66.  
  67.    ShowWindow(_hWnd, SW_MINIMIZE);
  68.    UpdateWindow(_hWnd);
  69.  
  70.    // Create hidden unowned-popup window that covers user's entire screen.
  71.    _hWndBlnk = CreateWindow(_szBlnkClass, NULL,
  72.       WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN),
  73.       GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, 0);
  74.  
  75.    if (_hWndBlnk == NULL) return(0);
  76.  
  77.    // Send WM_TIMER messages to unowned-popup window every second.
  78.    if (0 == SetTimer(_hWndBlnk, 1, 1000, NULL)) {
  79.       MessageBox(_hWnd, "Not enough timers!", _szAppName, MB_OK);
  80.       return(0);
  81.    }
  82.  
  83.    while (GetMessage(&msg, NULL, 0, 0)) {
  84.       TranslateMessage(&msg);
  85.       DispatchMessage(&msg);
  86.    }
  87.  
  88.    KillTimer(_hWndBlnk, 1);
  89.    DestroyWindow(_hWndBlnk);
  90.  
  91.    return(0);
  92. }
  93.  
  94.  
  95.  
  96. // ***************************************************************************
  97.  
  98. BOOL NEAR PASCAL RegisterWndClasses (HANDLE hInstance) {
  99.    WNDCLASS WndClass;
  100.  
  101.    WndClass.style         = 0;
  102.    WndClass.lpfnWndProc   = AppWndProc;
  103.    WndClass.cbClsExtra    = 0;
  104.    WndClass.cbWndExtra    = 0;
  105.    WndClass.hInstance     = hInstance;
  106.    WndClass.hIcon         = LoadIcon(hInstance, _szAppName);
  107.    WndClass.hCursor       = NULL;
  108.    WndClass.hbrBackground = NULL;
  109.    WndClass.lpszMenuName  = NULL;
  110.    WndClass.lpszClassName = _szAppName;
  111.    if (!RegisterClass(&WndClass)) return(0);
  112.  
  113.  
  114.    WndClass.style         = 0;
  115.    WndClass.lpfnWndProc   = BlnkWndProc;
  116.    WndClass.cbClsExtra    = 0;
  117.    WndClass.cbWndExtra    = 0;
  118.    WndClass.hInstance     = hInstance;
  119.    WndClass.hIcon         = LoadIcon(hInstance, _szAppName);
  120.    WndClass.hCursor       = NULL;
  121.  
  122.    // Unowned-popup window's background is always BLACK so that 
  123.    // contents of screen is removed.
  124.    WndClass.hbrBackground = GetStockObject(BLACK_BRUSH);
  125.  
  126.    WndClass.lpszMenuName  = NULL;
  127.    WndClass.lpszClassName = _szBlnkClass;
  128.    return(RegisterClass(&WndClass));
  129. }
  130.  
  131.  
  132. // ***************************************************************************
  133. // This function processes all messages sent to ScrnBlnk's main window.
  134.  
  135. LONG FAR PASCAL AppWndProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam) {
  136.    BOOL fCallDefProc = FALSE;
  137.    LONG lResult = 0;
  138.    HMENU hMenu;
  139.    FARPROC fpProc;
  140.    WORD wIdleTime;
  141.  
  142.    switch (wMsg) {
  143.       case WM_CREATE:
  144.          // Append the "Preferences" and "About" options to the system menu.
  145.          hMenu = GetSystemMenu(hWnd, 0);
  146.          AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
  147.          AppendMenu(hMenu, MF_STRING, IDM_PREFERENCES, "&Preferences...");
  148.          AppendMenu(hMenu, MF_STRING, IDM_ABOUT, "A&bout...");
  149.          DrawMenuBar(hWnd);
  150.  
  151.          // Install the WH_JOURNALRECORD hook filter function.
  152.          InstallJrnlHook(TRUE);
  153.          break;
  154.  
  155.       case WM_DESTROY:
  156.          // Remove the WH_JOURNALRECORD hook filter function.
  157.          InstallJrnlHook(FALSE);
  158.  
  159.          PostQuitMessage(0);
  160.          break;
  161.  
  162.       case WM_QUERYOPEN:
  163.          // Do not allow the application to open, show only as icon.
  164.          lResult = 0;
  165.          break;
  166.  
  167.       case WM_SYSCOMMAND:
  168.          switch (wParam & 0xfff0) {
  169.             case IDM_PREFERENCES:
  170.                // Prompt user for idle time in minutes.
  171.                fpProc = MakeProcInstance(PrefProc, _hInstance);
  172.  
  173.                // The last parameter is the current settings of _wMinutes.
  174.                wIdleTime = DialogBoxParam(_hInstance, "Preferences",
  175.                   hWnd, fpProc, _wMinutes);
  176.                FreeProcInstance(fpProc);
  177.  
  178.                // If wIdleTime == -1, the user pressed "Cancel"
  179.                // else wIdleTime is the idle time.
  180.                if ((int) wIdleTime != -1) _wMinutes = wIdleTime;
  181.                break;
  182.  
  183.             case IDM_ABOUT:
  184.                fpProc = MakeProcInstance(AboutProc, _hInstance);
  185.                DialogBox(_hInstance, "About", hWnd, fpProc);
  186.                FreeProcInstance(fpProc);
  187.                break;
  188.  
  189.             default:
  190.                fCallDefProc = TRUE; break;
  191.          }
  192.          break;
  193.  
  194.       default:
  195.          fCallDefProc = TRUE; break;
  196.    }
  197.  
  198.    if (fCallDefProc)
  199.       lResult = DefWindowProc(hWnd, wMsg, wParam, lParam);
  200.  
  201.    return(lResult);
  202. }
  203.  
  204. // ***************************************************************************
  205.  
  206. #define GETRANDOM(Min, Max) ((rand() % (int)(((Max)+1) - (Min))) + (Min))
  207.  
  208. #define DEGTORAD(Deg) ((Deg * 3.14159) / 180)
  209.  
  210. LONG FAR PASCAL BlnkWndProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam) {
  211.    BOOL fCallDefProc = FALSE, fForceStop = FALSE;
  212.    LONG lResult = 0;
  213.    WORD wXCenter, wYCenter, wCircle, wRadius, wTheta, wInc;
  214.    WORD wRed, wGreen, wBlue;
  215.    RECT rc;
  216.    HPEN hPen, hOldPen;
  217.    HDC hDC;
  218.    MSG msg;
  219.  
  220.    switch (wMsg) {
  221.       case WM_TIMER:
  222.  
  223.          // If windows is already visible, animate drawing.
  224.          if (!IsWindowVisible(hWnd)) {
  225.  
  226.             // Every second, check if the idle time has elapsed.
  227.             // Is system time minus the time of the last user event
  228.             // greater than the number of minutes the user specified?
  229.             if (GetTickCount() - GetLastEventTime() > _wMinutes * 60000ul) {
  230.                ShowWindow(hWnd, SW_SHOW);
  231.                ShowCursor(0);
  232.             }
  233.             break;
  234.          }
  235.  
  236.          // Animate the circle drawing in the blank window.
  237.          GetWindowRect(hWnd, &rc);
  238.  
  239.          // Select random center point for circle.
  240.          wXCenter = GETRANDOM(0, rc.right - 1);
  241.          wYCenter = GETRANDOM(0, rc.bottom - 1);
  242.  
  243.          // Select random radius length for circle
  244.          wRadius = GETRANDOM(rc.right / 20, rc.right - 1);
  245.  
  246.          // Select random theta angle.
  247.          wInc = GETRANDOM(1, 5);
  248.  
  249.          hDC = GetDC(hWnd);
  250.          SetBkMode(hDC, TRANSPARENT);
  251.  
  252.          // Draw circle twice:
  253.          //   1st time: Circle is drawn in multicolors
  254.          //   2nd time: Circle is draw in all black effectively removing it.
  255.          for (wCircle = 0; !fForceStop && wCircle < 2; wCircle++) {
  256.  
  257.             for (wTheta = 0; wTheta < 360; wTheta += wInc) {
  258.  
  259.                // Drawing takes a long time, so check if user becomes active
  260.                // again by pressing a mouse button or key on the keyboard.
  261.                fForceStop =
  262.                   PeekMessage(&msg, hWnd, WM_KEYFIRST, WM_KEYLAST,
  263.                      PM_NOYIELD | PM_NOREMOVE) ||
  264.                   PeekMessage(&msg, hWnd, WM_LBUTTONDOWN, WM_MOUSELAST,
  265.                      PM_NOYIELD | PM_NOREMOVE);
  266.  
  267.                // If either type of event (mouse or keyboard) in queue,
  268.                // stop drawing the circle prematurely.
  269.                if (fForceStop) break;
  270.  
  271.                // Select a random color for the spoke of the circle.
  272.                // Do not allow a spoke to be BLACK (RGB(0, 0, 0)).
  273.                do {
  274.                   wRed   = GETRANDOM(0, 32);
  275.                   wGreen = GETRANDOM(0, 32);
  276.                   wBlue  = GETRANDOM(0, 32);
  277.                } while (wRed == 0 && wGreen == 0 && wBlue == 0);
  278.  
  279.                // Create a pen using a cycling style and the random color.
  280.                hPen = CreatePen((wTheta % 3), 1,
  281.                   RGB(wRed * 7, wGreen * 7, wBlue * 7));
  282.                hOldPen = SelectObject(hDC, hPen);
  283.  
  284.                // Start at the center of the circle and draw the spoke.
  285.                MoveTo(hDC, wXCenter, wYCenter);
  286.                LineTo(hDC,
  287.                   (int) (wRadius * cos(DEGTORAD(wTheta))) + wXCenter,
  288.                   (int) (wRadius * sin(DEGTORAD(wTheta))) + wYCenter);
  289.  
  290.                // Restore original pen in hDC and delete the created pen.
  291.                SelectObject(hDC, hOldPen);
  292.                DeleteObject(hPen);
  293.             }
  294.  
  295.             // For the 2nd time the circle is drawn, set the ROP2 code 
  296.             // R2_BLACK.  This causes all of the spokes to be painted black
  297.             // no matter what colors were used to create the pen.
  298.             SetROP2(hDC, R2_BLACK);
  299.          }
  300.          ReleaseDC(hWnd, hDC);
  301.          break;
  302.  
  303.       case WM_LBUTTONDOWN:
  304.       case WM_MBUTTONDOWN:
  305.       case WM_RBUTTONDOWN:
  306.       case WM_KEYDOWN:
  307.       case WM_SYSKEYDOWN:
  308.          // If any of the above events occur, the user is active and we must
  309.          // show the mouse cursor and hide our self.
  310.          ShowCursor(1);
  311.          ShowWindow(hWnd, SW_HIDE);
  312.          break;
  313.  
  314.       default:
  315.          fCallDefProc = TRUE; break;
  316.    }
  317.  
  318.    if (fCallDefProc)
  319.       lResult = DefWindowProc(hWnd, wMsg, wParam, lParam);
  320.  
  321.    return(lResult);
  322. }
  323.  
  324.  
  325. // ***************************************************************************
  326. // This function processes all messages sent to the Preferences dialog box.
  327.  
  328. BOOL FAR PASCAL PrefProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam) {
  329.    BOOL fProcessed = TRUE, fTranslated;
  330.    WORD wMinutes;
  331.  
  332.    switch (wMsg) {
  333.  
  334.       case WM_INITDIALOG:
  335.          // The lParam parameter contains the current settings of the 
  336.          // _wMinutes variable.  This should be shown as the default value.
  337.          SetDlgItemInt(hDlg, ID_MINUTES, (WORD) lParam, FALSE);
  338.          break;
  339.  
  340.       case WM_COMMAND:
  341.          switch (wParam) {
  342.             case IDOK:
  343.                if (HIWORD(lParam) != BN_CLICKED) break;
  344.                wMinutes =
  345.                   GetDlgItemInt(hDlg, ID_MINUTES, &fTranslated, FALSE);
  346.                if (!fTranslated || wMinutes == 0) {
  347.                   MessageBox(hDlg, "Invalid value for minutes.",
  348.                      _szAppName, MB_OK); break;
  349.                }
  350.                // Return the new value that the user entered.
  351.                EndDialog(hDlg, wMinutes);
  352.                break;
  353.                   
  354.             case IDCANCEL:
  355.                if (HIWORD(lParam) != BN_CLICKED) break;
  356.                // Return -1 indicating that the user pressed "Cancel".
  357.                EndDialog(hDlg, -1);
  358.                break;
  359.  
  360.             default:
  361.                break;
  362.          }
  363.          break;
  364.  
  365.       default:
  366.          fProcessed = FALSE; break;
  367.    }
  368.    return(fProcessed);
  369. }
  370.  
  371.  
  372. // ***************************************************************************
  373. // This function processes all messages sent to the About dialog box.
  374.  
  375. BOOL FAR PASCAL AboutProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam) {
  376.    BOOL fProcessed = TRUE;
  377.    char szBuffer[100];
  378.  
  379.    switch (wMsg) {
  380.  
  381.       case WM_INITDIALOG:
  382.          // Set version static window to have date and time of compilation.
  383.          wsprintf(szBuffer, "%s at %s", (LPSTR) __DATE__, (LPSTR) __TIME__);
  384.          SetWindowText(GetDlgItem(hDlg, ID_VERSION), szBuffer);
  385.          break;
  386.  
  387.       case WM_COMMAND:
  388.          switch (wParam) {
  389.             case IDOK: case IDCANCEL:
  390.                if (HIWORD(lParam) == BN_CLICKED)
  391.                   EndDialog(hDlg, wParam);
  392.                break;
  393.  
  394.             default:
  395.                break;
  396.          }
  397.          break;
  398.  
  399.       default:
  400.          fProcessed = FALSE; break;
  401.    }
  402.    return(fProcessed);
  403. }
  404.